home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-20 / nos_kit3.zip / TNC_ASH.ZIP / VDG_KISS.ASM < prev    next >
Assembly Source File  |  1987-05-26  |  48KB  |  1,807 lines

  1. ; *********************************************************************
  2. ; **  KISS Protocol Program for stock VADCG/ASHBY-2716   KISS V1.03  **
  3. ; **              By: Mike Bruski, AJ9X                    08FEB87   **
  4. ; *********************************************************************
  5.  
  6. ;     Change History:
  7. ;       When       Who         What
  8. ;    26JAN87    AJ9X         Initial Version (V1.00)
  9. ;    31JAN87    AJ9X        Removed auto baud rate detection &
  10. ;                interval timer driven by 8253 (V1.01)
  11. ;    07FEB87    AJ9X        Send last character and release cell
  12. ;                on transmitted async. frames (V1.02)
  13. ;    08FEB87    AJ9X        Disabled early end of frame interrupt
  14. ;                from 8273 to prevent transmitter
  15. ;                shutdown prior to sending CRC and
  16. ;                closing flag (V1.03)
  17. ;    PAGE
  18.  
  19. ;
  20. ;    8250 SIO Controller Equates
  21.  
  22. ;    Registers:
  23.  
  24. RBR    EQU    0        ; RECEIVE BUFFER REGISTER            [R]
  25. THR    EQU    0        ; TRANSMIT HOLDING REGISTER          [W]
  26. DLL    EQU    0        ; DRIVER LATCH (LSB)                 [W]
  27. DLM    EQU    1        ; DRIVER LATCH (MSB)                 [W]
  28. IER    EQU    1        ; INTERRUPT ENABLE REGISTER          [W]
  29. IIR    EQU    2        ; INTERRUPT IDENTIFICATION REGISTER  [R]
  30. LCR    EQU    3        ; LINE CONTROL REGISTER            [R/W]
  31. MCR    EQU    4        ; MODEM CONTROL REGISTER           [R/W]
  32. LSR    EQU    5        ; LINE STATUS REGISTER             [R/W]
  33. MSR    EQU    6        ; MODEM STATUS REGISTER            [R/W]
  34.  
  35. ;    Equates for Interrupt Enable Register
  36.  
  37. ERI    EQU    00000001B    ; ENABLE RECEIVE DATA INTERRUPTS
  38. ETI    EQU    00000010B    ; ENABLE TRANSMIT DATA INTERRUPTS
  39. ELI    EQU    00000100B    ; ENABLE LINE STATUS INTERRUPTS
  40. EMI    EQU    00001000B    ; ENABLE MODEM STATUS INTERRUPTS
  41.  
  42. ;    Equates for Line Status Register
  43.  
  44. DR    EQU    00000001B    ; DATA READY
  45. OE    EQU    00000010B    ; OVERRUN ERROR
  46. PE    EQU    00000100B    ; PARITY ERROR
  47. FE    EQU    00001000B    ; FRAMING ERROR
  48. BI    EQU    00010000B    ; BREAK INTERRUPT
  49. THRE    EQU    00100000B    ; TRANSMIT HOLDING REGISTER EMPTY
  50. TSRE    EQU    01000000B    ; TRANSMIT SHIFT REGISTER EMPTY
  51.  
  52. ;    Equates for Modem Status Register
  53.  
  54. DCTS    EQU    00000001B    ; DELTA CLEAR-TO-SEND
  55. DDSR    EQU    00000010B    ; DELTA DATA-SET-READY
  56. TERI    EQU    00000100B    ; TRAILING EDGE OF RING INDICATOR
  57. DCD    EQU    00001000B    ; DELTA CARRIER DETECT
  58. TCTS    EQU    00010000B    ; TERMINAL CLEAR-TO-SEND
  59. TDSR    EQU    00100000B    ; TERMINAL DATA-SET-READY
  60. TRI    EQU    01000000B    ; TERMINAL RING INDICATOR
  61. TCD    EQU    10000000B    ; TERMINAL CARRIER DETECT
  62.  
  63. ;    Equates for Line Control Register
  64.  
  65. D5    EQU    00000000B    ; WORD LENGTH = 5 BITS
  66. D6    EQU    00000001B    ; WORD LENGTH = 6 BITS
  67. D7    EQU    00000010B    ; WORD LENGTH = 7 BITS
  68. D8    EQU    00000011B    ; WORD LENGTH = 8 BITS
  69. S1    EQU    00000000B    ; STOP BITS = 1
  70. S2    EQU    00000100B    ; STOP BITS = 2
  71. NP    EQU    00000000B    ; NO PARITY
  72. PEN    EQU    00001000B    ; PARITY ENABLE
  73. OP    EQU    00000000B    ; ODD PARITY
  74. EP    EQU    00010000B    ; EVEN PARITY SELECT
  75. STP    EQU    00100000B    ; STICK PARITY
  76. SB    EQU    01000000B    ; SET BREAK
  77. DLA    EQU    10000000B    ; DIVISOR LATCH ACCESS
  78.  
  79. ;    Equates for Modem Control Register
  80.  
  81. ADTR    EQU    00000001B    ; ASYNCHRONOUS DATA-TERMINAL-READY
  82. ARTS    EQU    00000010B    ; ASYNCHRONOUS REQUEST-TO-SEND
  83. OUT1    EQU    00000100B    ; ASYNCHRONOUS CARRIER DETECT (LOOP=RI)
  84. OUT2    EQU    00001000B    ; NO CONNECTION ON VADCG (LOOP=CD)
  85. LOOP    EQU    00010000B    ; LOOPBACK DIAGNOSTIC ENABLE
  86.  
  87. ;    Equates for Interrupt Identification Register
  88.  
  89. AIPM    EQU    00000001B    ; ASYNC INT. PENDING MASK
  90. ;                   INTERRUPT IS PENDING IF NOT SET
  91. IIM    EQU    00000110B    ; INTERRUPT IDENTIFICATION MASK
  92. RLSI    EQU    00000110B    ; RECEIVER LINE STATUS INTERRUPT
  93. RDAI    EQU    00000100B    ; RECEIVED DATA AVAILABLE INTERRUPT
  94. TREI    EQU    00000010B    ; TRANSMIT HOLDING REG. EMPTY INTERRUPT
  95. MSI    EQU    00000000B    ; MODEM STATUS INTERRUPT
  96. ;    PAGE
  97.  
  98. ;
  99. ;    8273 HDLC Controller Equates
  100.  
  101. ;    Registers:
  102.  
  103. STAT73    EQU    10H        ; STATUS REGISTER                    [R]
  104. CMND73    EQU    10H        ; COMMAND REGISTER                   [W]
  105. PARM73    EQU    11H        ; PARAMETER REGISTER                 [W]
  106. RESL73    EQU    11H        ; RESULTS REGISTER                   [R]
  107. TEST73    EQU    12H        ; TEST REGISTER                      [W]
  108. TXIR73    EQU    12H        ; TRANSMIT INTERRUPT RESULTS REGISTER[R]
  109. RXIR73    EQU    13H        ; RECEIVE INTERRUPT RESULTS REGISTER [R]
  110. TXDR73    EQU    18H        ; TRANSMIT DATA REGISTER             [W]
  111. RXDR73    EQU    20H        ; RECEIVE DATA REGISTER              [R]
  112.  
  113. ;    Equates for STAT73
  114.  
  115. TXIRA    EQU    00000001B    ; TRANSMIT INTERRUPT RESULTS AVAILABLE
  116. RXIRA    EQU    00000010B    ; RECEIVE INTERRUPT RESULTS AVAILABLE
  117. TINTP    EQU    00000100B    ; TRANSMIT INTERRUPT STILL PENDING
  118. RINTP    EQU    00001000B    ; RECEIVE INTERRUPT STILL PENDING
  119. CRBF    EQU    00010000B    ; COMMAND RESULTS BUFFER FULL
  120. CPBF    EQU    00100000B    ; COMMAND PARAMETER BUFFER FULL
  121. CBF    EQU    01000000B    ; COMMAND BUFFER FULL
  122. CBSY    EQU    10000000B    ; COMMAND BUFFER BUSY
  123.  
  124. ;    Equates for TXIR73
  125.  
  126. EXI    EQU    00001100B    ; EARLY TRANSMIT INTERRUPT
  127. FTC    EQU    00001101B    ; FRAME TRANSMISSION COMPLETE
  128. DMAU    EQU    00001110B    ; DMA UNDERRUN (not used)
  129. CTSE    EQU    00001111B    ; CLEAR-TO-SEND ERROR
  130. ATC    EQU    00010000B    ; ABORT TRANSMISSION COMPLETE
  131.  
  132. ;    Equates for RXIR73
  133.  
  134. CRCE    EQU    00000011B    ; CRC ERROR
  135. FAD    EQU    00000100B    ; FRAME ABORT DETECTED
  136. IFD    EQU    00000101B    ; IDLE FLAG DETECTED
  137. EOPD    EQU    00000110B    ; EOP DETECTED (not used)
  138. SFD    EQU    00000111B    ; SHORT FRAME DETECTED (< 32 BITS)
  139. DMAO    EQU    00001000B    ; DMA OVERRUN
  140. MBO    EQU    00001001B    ; MEMORY BUFFER OVERFLOW
  141. CDF    EQU    00001010B    ; CARRIER DETECT FAILURE
  142. RIO    EQU    00001011B    ; RECEIVE INTERRUPT OVERRUN
  143.  
  144. ;    Equates for PORT A (input)
  145.  
  146. MCTS    EQU    00000001B    ; MODEM CLEAR-TO-SEND
  147. MCD    EQU    00000010B    ; MODEM CARRIER DETECT
  148. PA2    EQU    00000100B    ; SPARE PORT INPUT
  149. PA3    EQU    00001000B    ; SPARE PORT INPUT
  150. PA4    EQU    00010000B    ; SPARE PORT INPUT
  151.  
  152. ;    Equates for PORT B (output)
  153.  
  154. MRTS    EQU    00000001B    ; MODEM REQUEST-TO-SEND
  155. PB1    EQU    00000010B    ; SPARE PORT OUTPUT
  156. PB2    EQU    00000100B    ; SPARE PORT OUTPUT
  157. PB3    EQU    00001000B    ; SPARE PORT OUTPUT
  158. PB4    EQU    00010000B    ; SPARE PORT OUTPUT
  159. FD    EQU    00100000B    ; FLAG DETECT
  160. ;    PAGE
  161.  
  162. ;
  163. ;    8253 Interval Timer Equates (VDS-1 only)
  164.  
  165. ;    Registers:
  166.  
  167. PIT0    EQU    28H        ; COUNTER PORT 0 (8273 BAUD RATE)
  168. PIT1    EQU    29H        ; COUNTER PORT 1 (8085 TRAP)
  169. PIT2    EQU    2AH        ; COUNTER PORT 2
  170. ITCP    EQU    2BH        ; INTERVAL TIMER CONTROL PORT
  171.  
  172. ;    Equates for ITCP (control word)
  173.  
  174. ;    Register selection field
  175. C0    EQU    00000000B    ; COUNTER 0
  176. C1    EQU    01000000B    ; COUNTER 1
  177. C2    EQU    10000000B    ; COUNTER 2
  178.  
  179. ;    Read/Load control field
  180. LC    EQU    00000000B    ; LATCH COUNT
  181. RLL    EQU    00010000B    ; READ/LOAD LSB ONLY
  182. RLM    EQU    00100000B    ; READ/LOAD MSB ONLY
  183. RLB    EQU    00110000B    ; READ/LOAD LSB FIRST, MSB NEXT
  184.  
  185. ;    Mode control field
  186. MD0    EQU    00000000B    ; MODE 0, TIMED INTERRUPT
  187. MD1    EQU    00000010B    ; MODE 1, RETRIGGERABLE ONE SHOT
  188. MD2    EQU    00000100B    ; MODE 2, RATE GENERATOR
  189. MD3    EQU    00000110B    ; MODE 3, SQUARE WAVE GENERATOR
  190. MD4    EQU    00001000B    ; MODE 4, SOFTWARE TRIGGERED STROBE
  191. MD5    EQU    00001010B    ; MODE 5, HARDWARE TRIGGERED STROBE
  192.  
  193. ;    Counter Type field
  194. BIN    EQU    00000000B    ; 16 BIT BINARY
  195. BCD    EQU    00000001B    ;  4 DECADE BCD
  196.  
  197. ;    Equates for PIT0 (Synchronous Baud Rate Values)
  198.  
  199. SBR9600    EQU    4        ; 9600 baud
  200. SBR4800    EQU    8        ; 4800 baud
  201. SBR2400    EQU    16        ; 2400 baud
  202. SBR1200    EQU    32        ; 1200 baud (default)
  203. SBR600    EQU    64        ;  600 baud
  204. SBR300    EQU    128        ;  300 baud
  205.  
  206. ;    Equates for PIT1 (Cyclic Timer) - NOT USING THIS YET
  207. ;       Input = 38.4Khz from pin 4 of U40
  208.  
  209. MS100    EQU    3840        ; 100ms timer value 
  210. MS50    EQU    1920        ;  50ms timer value
  211. MS20    EQU    768        ;  20ms timer value
  212. MS10    EQU    384        ;  10ms timer value (default)
  213.  
  214. ;  Use these guys for S/W timing (now for all VADCG & ASHBY)
  215. IC100    EQU    2297        ; Interval count for 100ms
  216. IC10    EQU    230        ; Interval count for 10ms
  217.  
  218. ;    Equates for PIT2 (Random Number Generator)
  219. ;    Input = 38.4Khz from pin 4 of U40
  220.  
  221. SEED    EQU    32767
  222. ;    PAGE
  223.  
  224. ;
  225. ;    8085 CPU Interrupt Mask Register Equates
  226.  
  227. ACD    EQU    00000001B    ; RST5.5, ASYNC. INTERRUPTS DISABLED
  228. STD    EQU    00000010B    ; RST6.5, SYNC. XMTR INT. DISABLED
  229. SRD    EQU    00000100B    ; RST7.5, SYNC. RCVR INT. DISABLED
  230. MSE    EQU    00001000B    ; INTERRUPT MASK ENABLED
  231.  
  232. ;
  233. ;    Special Character Equates
  234. EOS    EQU    00H
  235. LF    EQU    0AH
  236. CR    EQU    0DH
  237. COMMA    EQU    2CH
  238. PERIOD    EQU    2EH
  239. FEND    EQU    0C0H
  240. FESC    EQU    0DBH
  241. TFEND    EQU    0DCH
  242. TFESC    EQU    0DDH
  243.  
  244. ;
  245. ;    End Action (Event) Flags
  246. SRFC    EQU    00000001B    ; SYNC. RECEIVER FRAME COMPLETION
  247. ARFC    EQU    00000010B    ; ASYNC. RECEIVER FRAME COMPLETION
  248. STFC    EQU    00000100B    ; SYNC. TRANSMITTER FRAME COMPLETION
  249. ATFC    EQU    00001000B    ; ASYNC. TRANSMITTER FRAME COMPLETION
  250. EXTI    EQU    00010000B    ; EXPIRED TIMER
  251. SRDD    EQU    00100000B    ; SYNC. RECEIVER DISCARDING DATA
  252. ARDD    EQU    01000000B    ; ASYNC. RECEIVER DISCARDING DATA
  253.  
  254. ;
  255. ;    Miscellaneous Equates
  256. WDVAL    EQU    220        ; DEFAULT WATCH DOG DELAY FOR 1200 BAUD
  257. ;    PAGE
  258.  
  259. ;
  260. ;    Static Random Access Memory (SRAM) Equates
  261.  
  262. ;    LORAM    HIRAM    CONFIGURATION
  263. ;
  264. ;    1000H    1FFFH  *ASHBY with 2716 ROMs or Standard VADCG
  265. ;    2000H    2FFFH    ASHBY with 2732 ROMs
  266. ;    7000H    7FFFH    VADCG with California memory mods
  267. ;    8000H    8FFFH    VADCG with early AMRAD memory mods
  268. ;    8000H    9FFFH    VADCG with VDS-1 (8K RAM)
  269. ;    8000H    FFFFH    VADCG with VDS-1 (32K RAM)
  270. ;    
  271.  
  272. LORAM    EQU    1000H        ; BEGINNING OF SRAM
  273. HIRAM    EQU    1FFFH        ; END OF SRAM
  274. STACK    EQU    LORAM+64H    ; BEGINNING OF PROGRAM STACK
  275. EA$FLG    EQU    STACK+2        ; END ACTION FLAGS
  276.  
  277. ;    Interval Timer Variables
  278. PVAL    EQU    EA$FLG+1    ; PERSISTENCE VALUE
  279. SVAL    EQU    PVAL+1        ; SLOT-TIME VALUE
  280. RVAL    EQU    SVAL+1        ; RELAY DELAY VALUE
  281. TVAL    EQU    RVAL+1        ; SQUELCH TAIL DELAY VALUE
  282. TICKS    EQU    TVAL+1        ; TICK COUNTER FOR S/W TIMING
  283. IT$FLG    EQU    TICKS+2        ; 0 = INACTIVE, 1 = ACTIVE
  284. IT$VAL    EQU    IT$FLG+1    ; CURRENT TIMER VALUE
  285. IT$STA    EQU    IT$VAL+2    ; CURRENT TIMER STATE
  286.  
  287. ;    Asynchronous Receiver Variables
  288. AR$HC    EQU    IT$STA+1    ; CURRENT FRAME HEAD
  289. AR$BP    EQU    AR$HC+2        ; CURRENT BUFFER POINTER
  290. AR$FSZ    EQU    AR$BP+2        ; CURRENT FRAME SIZE
  291. AR$FH    EQU    AR$FSZ+2    ; COMPLETED FRAME HEAD
  292. AR$FS    EQU    AR$FH+2        ; COMPLETED FRAME SIZE
  293. AR$STA    EQU    AR$FS+2        ; CURRENT MACHINE STATE
  294.  
  295. ;    Asynchronous Transmitter Variables
  296. AT$BP    EQU    AR$STA+1    ; CURRENT BUFFER POINTER
  297. AT$QS    EQU    AT$BP+2        ; QUEUE SIZE
  298. AT$QR    EQU    AT$QS+1        ; QUEUE READ POINTER
  299. AT$QW    EQU    AT$QR+2        ; QUEUE WRITE POINTER
  300. AT$STA    EQU    AT$QW+2        ; CURRENT MACHINE STATE
  301.  
  302. ;    Synchronous Receiver Variables
  303. SR$HC    EQU    AT$STA+1    ; CURRENT FRAME HEAD
  304. SR$BP    EQU    SR$HC+2        ; CURRENT BUFFER POINTER
  305. SR$FR    EQU    SR$BP+2        ; CURRENT FRAME RESULTS
  306. SR$STA    EQU    SR$FR+1        ; CURRENT MACHINE STATE
  307.  
  308. ;    Synchronous Transmitter Variables
  309. ST$BP    EQU    SR$STA+1    ; CURRENT BUFFER POINTER
  310. ST$FR    EQU    ST$BP+2        ; CURRENT FRAME RESULTS
  311. ST$QS    EQU    ST$FR+1        ; QUEUE SIZE
  312. ST$QR    EQU    ST$QS+1        ; QUEUE READ POINTER
  313. ST$QW    EQU    ST$QR+2        ; QUEUE WRITE POINTER
  314.  
  315. ;    Synchronous Command Buffers
  316. SRACT    EQU    ST$QW+2        ; RECEIVER ACTIVATION COMMAND
  317. STACT    EQU    SRACT+4        ; TRANSMITTER ACTIVATION COMMAND
  318.  
  319. ;    Asynchronous Transmitter Queue
  320. AT$QT    EQU    STACT+4        ; TOP OF QUEUE
  321. AT$QB    EQU    AT$QT+(2*64)    ; BOTTOM OF QUEUE
  322.  
  323. ;    Synchronous Transmitter Queue
  324. ST$QT    EQU    AT$QB+2        ; TOP OF QUEUE
  325. ST$QB    EQU    ST$QT+(4*64)    ; BOTTOM OF QUEUE
  326.  
  327. ;    Buffer area
  328. FL$HC    EQU    ST$QB+4
  329. NCELL    EQU    (HIRAM-FL$HC+2)/128
  330. BAREA    EQU    (HIRAM-NCELL*128)+1 ; BEGINNING OF BUFFER AREA
  331. NLIST    EQU    BAREA-2        ; # OF AVAILABLE CELLS IN FREE LIST
  332. ;    PAGE
  333.  
  334. BASE    EQU    0
  335.     ORG    BASE        ; PROGRAM ORIGIN
  336.  
  337. ;
  338. ;    Here we begin -
  339. ;    A good place to start is with the interrupt vectors
  340.  
  341. ;
  342. ;    RST0 - [H/W AND S/W INTERRUPT]
  343. ;    ENTER HERE ON POWER UP AND WHEN THE RESET
  344. ;    BUTTON IS SMASHED TO INITIALIZE THE H/W
  345. ;    AND MEMORY.  MIGHT ALSO VECTOR HERE IN S/W
  346. ;    IF EVERYTHING IS SO MESSED UP THE TNC CAN'T
  347. ;    FUNCTION CORRECTLY.
  348.  
  349. RST0    EQU    $        ; RESTART (WARM & COLD)
  350.     JMP    INIT
  351.  
  352.     ORG    BASE+08H
  353.  
  354. ;
  355. ;    RST1 - [S/W INTERRUPT]
  356. ;    ENTER HERE TO RETURN FROM AN INTERRUPT.  THE FIRST
  357. ;    ITEM ON THE STACK WILL BE A RETURN ADDRESS TO THE
  358. ;    RST INSTRUCTION WHICH GOT US HERE SO IT GETS WASTED.
  359. ;    NEXT THE PROGRAM STATUS WORD (ACCUMULATOR & FLAGS)
  360. ;    ARE RESTORE, INTERRUPTS ARE RE-ENABLED AND THE REST
  361. ;    IS HISTORY.
  362.  
  363. RST1    EQU    $
  364.     POP    PSW        ; PURGE BOGUS ADDRESS FROM STACK
  365.     POP    PSW        ; RESTORE PROGRAM STATUS WORD
  366.     EI            ; UNGATE INTERRUPTS
  367.     RET            ; RETURN TO POINT OF INTERRUPT
  368.  
  369.     ORG    BASE+10H
  370.  
  371. ;
  372. ;    RST2 - [S/W INTERRUPT]
  373. ;    NO FUNCTION
  374.  
  375. RST2    EQU    $
  376.     RET
  377.  
  378.     ORG    BASE+18H
  379.  
  380. ;
  381. ;    RST3 - [S/W INTERRUPT]
  382. ;    NO FUNCTION
  383.  
  384. RST3    EQU    $
  385.     RET
  386.  
  387.     ORG    BASE+20H
  388.  
  389. ;
  390. ;    RST4 - [S/W INTERRUPT]
  391. ;    NO FUNCTION
  392.  
  393. RST4    EQU    $
  394.     RET
  395.  
  396.     ORG    BASE+24H
  397.  
  398. ;
  399. ;    TRAP - [NON MASKABLE H/W INTERRUPT]
  400. ;    NOT USED
  401.  
  402. TRAP    EQU    $
  403.     EI
  404.     RET
  405.  
  406.     ORG    BASE+28H
  407.  
  408. ;
  409. ;    RST5 - [S/W INTERRUPT]
  410. ;    NO FUNCTION
  411.  
  412. RST5    EQU    $
  413.     RET
  414.  
  415.     ORG    BASE+2CH
  416.  
  417. ;
  418. ;    RST5.5 - [MASKABLE H/W INTERRUPT]
  419. ;    VECTOR HERE WHEN A SIGNAL IS DETECTED ON PIN 9 OF
  420. ;    THE 8085.  THE 8250 WILL ASSERT THIS PIN WHEN ONE
  421. ;    OF THE FOLLOWING OCCURS; TRANSMIT BUFFER EMPTY,
  422. ;    RECEIVE CHARACTER AVAILABLE, RECEIVER OVERRUN,
  423. ;    RECEIVER PARITY ERROR, RECEIVER FRAMING ERROR,
  424. ;    BREAK INTERRUPT, DELTA CTS, DELTA DSR, RING INDICATE
  425. ;    OR RECEIVE LINE SIGNAL DETECT.
  426.  
  427. RST55    EQU    $
  428.     JMP    AIRC    ; GOTO ASYNC. INTERRUPT RESPONSE CODE
  429.  
  430.     ORG    BASE+30H
  431.  
  432. ;
  433. ;    RST6 - [S/W INTERRUPT]
  434. ;    NO FUNCTION
  435.  
  436. RST6    EQU    $
  437.     RET
  438.  
  439.     ORG    BASE+34H
  440.  
  441. ;
  442. ;    RST6.5 - [MASKABLE H/W INTERRUPT]
  443. ;    VECTOR HERE WHEN A SIGNAL IS DETECTED ON PIN 8 OF
  444. ;    THE 8085.  THE 8273 WILL ASSERT THIS PIN WHEN THE
  445. ;    SYNCHRONOUS TRANSMITTER REQUIRES SERVICE.
  446.  
  447. RST65    EQU    $
  448.     JMP    STIRC    ; GOTO SYNC. XMTR INTERRUPT RESPONSE CODE
  449.  
  450.     ORG    BASE+38H
  451.  
  452. ;
  453. ;    RST7 - [S/W INTERRUPT]
  454. ;    NO FUNCTION
  455.  
  456. RST7    EQU    $
  457.     RET
  458.  
  459.     ORG    BASE+3CH
  460.  
  461. ;
  462. ;    RST7.5 - [MASKABLE H/W INTERRUPT]
  463. ;    VECTOR HERE WHEN A SIGNAL IS DETECTED ON PIN 7 OF
  464. ;    THE 8085.  THE 8273 WILL ASSERT THIS PIN WHEN THE
  465. ;    SYNCHRONOUS RECEIVER REQUIRES SERVICE.
  466.  
  467. RST75    EQU    $
  468.     JMP    SRIRC    ; GOTO SYNC. RCVR INTERRUPT RESPONSE CODE
  469. ;    PAGE
  470.  
  471. ;
  472. ;    Initialize Hardware
  473. ;    Branch here for critical S/W errors or H/W reset
  474.  
  475. ;    Begin by reseting the 8250, 8253, and 8273
  476. INIT    EQU    $
  477.     DI            ; GATE INTERRUPTS
  478.     MVI    A,1        ; FIRST HALF OF 8273 RESET COMMAND
  479.     OUT    TEST73        ; ISSUE COMMAND
  480. ;  Book says to delay at least 10 tcycles then issue second half
  481.     XRA    A        ; A <-- 0              [ 4 tcy]
  482.     OUT    MCR        ; DROP 8250 DTR & RTS  [10 tcy]
  483.     OUT    IER        ; KILL 8250 INTERRUPTS [10 tcy]
  484. ;  This should be enough delay
  485.     OUT    TEST73        ; SECOND HALF OF 8273 RESET COMMAND
  486.     IN    RBR        ; FLUSH THE 8250 INPUT REGISTER
  487.     IN    RBR
  488.  
  489. ;    H/W is now in an acceptable state, continue
  490.     LXI    SP,STACK    ; SET STACK POINTER
  491.  
  492. ;    Now clear SRAM
  493.     LXI    D,HIRAM        ; DE <-- HIGH SRAM ADDRESS
  494.     LXI    H,LORAM        ; HL <-- LOW SRAM ADDRESS
  495.  
  496. INIT1    EQU    $
  497.     MVI    M,0        ; CLEAR NEXT LOCATION
  498.     INX    H        ; INCREMENT POINTER
  499.     MOV    A,D        ; A <-- MSB OF HIGH ADDRESS
  500.     CMP    H
  501.     JNZ    INIT1        ; IF (D <> H) GOTO INIT1
  502.     MOV    A,E        ; A <-- LSB OF HIGH ADDRESS
  503.     CMP    L
  504.     JNZ    INIT1        ; IF (E <> L) GOTO INIT1
  505.     MVI    M,0        ; ZERO LAST RAM LOCATION
  506.  
  507. ;    Initialize linked list of free cells
  508.     MVI    A,NCELL        ; A <-- # OF CELLS
  509.         STA    NLIST        ; SAVE IN SRAM
  510.     MOV    B,A        ; NOW MOVE CELL COUNT TO B
  511.     LXI    D,BAREA        ; DE <-- ADDRESS OF BUFFER AREA
  512.     DCR    B        ; SO THAT LAST CELL IS 0
  513. INIT2    EQU    $
  514.     LXI    H,128        ; HL <-- CELL SIZE
  515.     DAD    D        ; HL <-- ADDRESS OF NEXT CELL
  516.     XCHG            ; DE <-- NEXT, HL <-- CURRENT
  517.     MOV    M,E        ; CURRENT GETS LSB OF NEXT
  518.     INX    H
  519.     MOV    M,D        ; FOLLOWED BY MSB OF NEXT
  520.     DCR    B        ; B <-- B-1
  521.     JNZ    INIT2        ; IF (B <> 0) GOTO INIT2
  522.  
  523. ;    Initialize state variables
  524.     MVI    A,7
  525.     STA    AR$STA
  526.     MVI    A,0FFH
  527.     STA    AT$STA
  528.  
  529. ;    Initialize queue variables
  530.     LXI    H,AT$QT
  531.     SHLD    AT$QR
  532.     SHLD    AT$QW
  533.     LXI    H,ST$QT
  534.     SHLD    ST$QR
  535.     SHLD    ST$QW
  536.  
  537. ;    Initialize miscellaneous variables
  538.     LXI    H,0C002H    ; GENERAL RECEIVE COMMAND (8273)
  539.     SHLD    SRACT
  540.     LXI    H,330        ;*;; MAXIMUM ALLOWABLE PACKET LENGTH
  541.     SHLD    SRACT+2
  542.     LXI    H,0C802H    ; TRANSMIT FRAME COMMAND (8273)
  543.     SHLD    STACT
  544.     LXI    H,BAREA        ; H <-- ADDRESS OF FREE CELL AREA
  545.     SHLD    FL$HC        ; ESTABLISH FREE LIST HEAD CELL
  546.     LXI    H,MS10        ; H <-- CONSTANT FOR 10MS S/W TIMING
  547.     SHLD    TICKS        ; PRELOAD S/W COUNT VARIABLE
  548.     MVI    A,2        ; DEFAULT SQUELCH TAIL DELAY (20ms)
  549.     STA    TVAL
  550.     MVI    A,5        ; DEFAULT SLOT-TIME DELAY (50ms)
  551.     STA    SVAL
  552.     MVI    A,30        ; DEFAULT RELAY DELAY (300ms)
  553.     STA    RVAL
  554.     MVI    A,128        ; DEFAULT PERSISTENCE VALUE (0.5)
  555.     STA    PVAL
  556.  
  557. ;    Establish baud rate for asynchronous port
  558.     LXI    H,32        ; CONSTANT FOR 4800 BAUD
  559.     MVI    A,DLA        ; A <-- DIVISOR LATCH ACCESS FLAG
  560.     OUT    LCR        ; WRITE LINE CONTROL REGISTER
  561.     MOV    A,L        ; A <-- LSB OF BAUD RATE CONSTANT
  562.     OUT    DLL        ; WRITE DIVISOR LATCH LSB
  563.     MOV    A,H        ; A <-- MSB OF SAME
  564.     OUT    DLM        ; WRITE DIVISOR LATCH MSB
  565.     MVI    A,NP+D8+S2    ; NO PARITY, 8 DATA BITS, 2 STOP BITS
  566.     OUT    LCR        ; WRITE LINE CONTROL REGISTER
  567.  
  568. ;**********************************************************************
  569. ;    The following code segment is for VDS-1 users only!!!
  570. ;       Erase ';*;' in columns 1 thru 3 to assemble this segment.
  571. ;    Establish baud rate for synchronous port
  572. ;*;    MVI    A,C0+RLB+MD3+BIN ; 8253 MODE CONTROL WORD
  573. ;*;    OUT    ITCP        ; WRITE INTERVAL TIMER CONTROL PORT
  574. ;*;    LXI    H,SBR1200    ; CONSTANT FOR 1200 BAUD
  575. ;*;    MOV    A,L        ; A <-- LSB
  576. ;*;    OUT    PIT0        ; WRITE
  577. ;*;    MOV    A,H        ; A <-- MSB
  578. ;*;    OUT    PIT0        ; WRITE
  579.  
  580. ;    Activate the random number generator.
  581. ;*;    MVI    A,C2+RLB+MD3+BIN ; MODE CONTROL WORD
  582. ;*;    OUT    ITCP        ; WRITE
  583. ;*;    LXI    H,SEED        ; COUNTER VALUE
  584. ;*;    MOV    A,L        ; A <-- LSB
  585. ;*;    OUT    PIT2        ; WRITE
  586. ;*;    MOV    A,H        ; A <-- MSB
  587. ;*;    OUT    PIT2        ; WRITE
  588. ;**********************************************************************
  589.  
  590. ;    Asynchronous controller activation
  591. ;    RST5.5 to CPU is enabled first
  592.     MVI    A,ERI+ELI+EMI    ; RECEIVE AND LINE STATUS ENABLE
  593.     OUT    IER        ; WRITE INTERRUPT ENABLE REGISTER
  594.     MVI    A,ADTR+ARTS+OUT1 ; DTR, RTS, & CD FOR HOST
  595.     OUT    MCR        ; WRITE MODEM CONTROL REGISTER
  596.  
  597. ;    Synchronous controller activation follows
  598.     LXI    H,DTRANS
  599.     CALL    SCMDOT        ; SET DATA XFER MODE
  600.     LXI    H,OPMODE
  601.     CALL    SCMDOT        ; SET OPERATING MODE
  602.     LXI    H,SERIO
  603.     CALL    SCMDOT        ; SET SERIAL I/O MODE
  604.     LXI    H,SSDTR
  605.     CALL    SCMDOT        ; SET SYNCH. DTR TO MODEM
  606.     CALL    GCELL        ; GET A FREE CELL
  607.     XCHG            ; HL <-- CELL POINTER
  608.     SHLD    SR$BP        ; ESTABLISH NEW POINTERS
  609.     SHLD    SR$HC
  610.     MVI    M,0        ; RESET FORWARD POINTER
  611.     INX    H        ; ADVANCE POINTER
  612.     MVI    M,0
  613.     MVI    A,MSE        ; UNGATE RST5.5,RST6.5, & RST7.5
  614.     DB    30H        ; 8085 SIM INSTRUCTION
  615.     LXI    H,SRACT        ; SYNC. RECEIVER ACTIVATION COMMAND
  616.     CALL    SCMDOT
  617.  
  618. ;    LIGHTS! CAMERA! ACTION!
  619.     EI
  620. ;    PAGE
  621.  
  622. ;    TNC Executive Routine
  623.  
  624. EXEC    EQU    $
  625.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  626.     ANA    A
  627.     JNZ    EXEC2        ; IF (FLAGS SET) GOTO EXEC2
  628.     LDA    IT$FLG        ; A <-- TIMER CONTROL FLAG
  629.     ORA    A
  630.     JNZ    EXEC1        ; IF (TIMER ACTIVE) GOTO EXEC1
  631.     LXI    H,RPA        ; HL <-- READ PORT A COMMAND
  632.     CALL    SCMDOT        ; ISSUE COMMAND
  633.     CALL    SRSLIN        ; READ RESULTS
  634.     ANI    MCD        ; MASK MODEM CARRIER DETECT
  635.     JNZ    EXEC        ; IF (CHANNEL BUSY) GOTO EXEC
  636.     LDA    ST$QS        ; A <-- SYNC. XMTR QUEUE SIZE
  637.     ORA    A
  638.     JZ    EXEC        ; IF (EMPTY QUEUE) GOTO EXEC
  639.  
  640. ;**********************************************************************
  641. ;    The following code segment is for VDS-1 users only!!!
  642. ;       Remove ';*; in column 1 thru 3 to assemble this segment.
  643. ;  ASHBY and non-VDS VADCGs are rendered totally non-persistent
  644. ;*;    MVI    A,C2+RLL    ; READ CONTROL WORD
  645. ;*;    OUT    ITCP        ; WRITE INTERVAL TIMER CONTROL PORT
  646. ;*;    IN    PIT2        ; READ LSB OF TIMER (OUR RANDOM #)
  647. ;*;    MOV    B,A        ; COPY TO B FOR NOW
  648. ;*;    LDA    PVAL        ; A <-- PERSISTENCE VALUE
  649. ;*;    SUB    B
  650. ;*;    JNC    A5$S0A        ; IF (RANDOM < PVAL) GOTO A5$S0A
  651. ;**********************************************************************
  652.  
  653.     LDA    SVAL        ; A <-- SLOT-TIME VALUE
  654.     MOV    L,A        ; COPY TO L
  655.     XRA    A
  656.     MOV    H,A        ; EXTEND 16 BITS
  657.     SHLD    IT$VAL        ; ESTABLISH TIMER VALUE
  658.     STA    IT$STA        ; RECORD NEW STATE
  659.     INR    A
  660.     STA    IT$FLG        ; ACTIVATE TIMER
  661.     JMP    EXEC
  662.  
  663. ;    Active timer processing
  664. EXEC1    EQU    $
  665.     LHLD    TICKS        ; HL <-- S/W TIMER COUNT
  666.     DCX    H        ; DECREMENT
  667.     SHLD    TICKS        ; RECORD NEW COUNT
  668.     MOV    A,L        ; A <-- LSB OF COUNT
  669.     ORA    H        ; MSB
  670.     JNZ    EXEC        ; IF (NOT 0) GOTO EXEC
  671.     LXI    H,MS10        ; 10ms TIMER CONSTANT
  672.     SHLD    TICKS        ; RELOAD COUNT
  673.     LHLD    IT$VAL        ; HL <-- INTERVAL TIMER VALUE
  674.     DCX    H        ; DECREMENT TIMER
  675.     SHLD    IT$VAL        ; RECORD IT
  676.     MOV    A,L
  677.     ORA    H
  678.     JNZ    EXEC        ; IF (NOT EXPIRED) GOTO EXEC
  679.     STA    IT$FLG        ; DEACTIVATE TIMER
  680.     DI            ; GATE INTERRUPTS MOMENTARILY
  681.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  682.     ORI    EXTI        ; FLAG EXPIRED TIMER
  683.     STA    EA$FLG        ; RECORD FLAGS
  684.     EI            ; UNGATE
  685.     JMP    EXEC        ; BACK TO TOP
  686.  
  687. ;    End action processing
  688. EXEC2    EQU    $
  689.     RAR
  690.     JC    EX$A1        ; IF (SRFC) GOTO EX$A1
  691.     RAR
  692.     JC    EX$A2        ; IF (ARFC) GOTO EX$A2
  693.     RAR
  694.     JC    EX$A3        ; IF (STFC) GOTO EX$A3
  695.     RAR
  696.     JC    EX$A4        ; IF (ATFC) GOTO EX$A4
  697.     RAR
  698.     JC    EX$A5        ; IF (EXPIRED TIMER) GOTO EX$A5
  699.     RAR
  700.     JC    EX$A6        ; IF (SRDD) GOTO EX$A6
  701.     RAR
  702.     JC    EX$A7        ; IF (ARDD) GOTO EX$A7
  703.     JMP    EXEC        ; CONTINUE
  704.  
  705.  
  706.  
  707.  
  708.  
  709. ;    Here for synchronous receiver frame completion
  710. EX$A1    EQU    $
  711.     LHLD    SR$HC        ; HL <-- FRAME HEAD
  712.     PUSH    H        ; PRESERVE HL
  713.     DI            ; GATE INTERRUPTS MOMENTARILY
  714.     CALL    GCELL        ; GET A FREE CELL
  715.     EI            ; UNGATE
  716.     JZ    EX$A11        ; IF (BUFFERS FULL) GOTO EX$A11
  717.     XCHG            ; HL <-- CELL POINTER
  718.     SHLD    SR$BP        ; ESTABLISH NEW POINTERS
  719.     SHLD    SR$HC
  720.     MVI    M,0        ; RESET FORWARD POINTER
  721.     INX    H        ; ADVANCE POINTER
  722.     MVI    M,0
  723.     LXI    H,SRACT        ; HL <-- SYNC. RCVR ACTIVATION COMMAND
  724.     CALL    SCMDOT        ; ISSUE COMMAND
  725. EX$A11    EQU    $
  726.     MVI    B,0FFH-SRFC    ; B <-- FLAG MASK
  727.     DI            ; GATE INTERRUPTS MOMENTARILY
  728.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  729.     ANA    B        ; MASK OUT SRFC
  730.     STA    EA$FLG        ; WRITE FLAGS
  731.     EI            ; UNGATE
  732.     POP    H        ; RESTORE FRAME HEAD
  733.     LDA    SR$FR        ; A <-- FRAME RESULTS
  734.     CPI    0E0H        ; EXPECTED RESULTS
  735.     JNZ    EX$A12        ; IF (BAD FRAME) GOTO EX$A12
  736.     CALL    LATQ        ; ELSE LINK FRAME TO ASYNC. XMIT QUEUE
  737.     JMP    EXEC
  738. EX$A12    EQU    $
  739.     CALL    FCHN        ; RELEASE BAD FRAME
  740.     JMP    EXEC
  741.  
  742.  
  743.  
  744.  
  745.  
  746. ;    Here for asynchronous receiver frame completion
  747. EX$A2    EQU    $
  748.     MVI    B,0FFH-ARFC    ; B <-- FLAG MASK
  749.     DI            ; GATE INTERRUPTS MOMENTARILY
  750.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  751.     ANA    B        ; MASK OUT ARFC
  752.     STA    EA$FLG        ; WRITE FLAGS
  753.     EI            ; UNGATE
  754.     LHLD    AR$FS        ; HL <-- FRAME SIZE
  755.     MOV    B,H        ; COPY TO BC
  756.     MOV    C,L
  757.     LHLD    AR$FH        ; HL <-- FRAME HEAD
  758.     CALL    LSTQ        ; LINK FRAME TO SYNC. XMIT QUEUE
  759.     MVI    A,ADTR+ARTS+OUT1 ; DTR, RTS, AND CD FOR HOST
  760.     OUT    MCR        ; WRITE MODEM CONTROL REGISTER
  761.     JMP    EXEC
  762.  
  763.  
  764.  
  765.  
  766.  
  767. ;    Here for synchronous transmitter frame completion
  768. EX$A3    EQU    $
  769.     MVI    B,0FFH-STFC    ; B <-- FLAG MASK
  770.     DI            ; GATE INTERRUPTS MOMENTARILY
  771.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  772.     ANA    B        ; MASK OUT STFC
  773.     STA    EA$FLG        ; WRITE FLAGS
  774.     EI            ; UNGATE
  775.     LDA    ST$QS        ; A <-- QUEUE SIZE
  776.     ORA    A
  777.     JZ    EX$A32        ; IF (EMPTY QUEUE) GOTO EX$A32
  778.     DCR    A        ; ELSE DECREMENT COUNT
  779.     STA    ST$QS        ; WRITE NEW COUNT
  780.     LHLD    ST$QR        ; HL <-- QUEUE READ POINTER
  781.     LXI    D,-ST$QB    ; DE <-- QUEUE BOTTOM ADDRESS
  782.     PUSH    H
  783.     DAD    D
  784.     POP    H        ; RESTORE READ POINTER
  785.     JNC    EX$A31        ; IF (NOT BOTTOM) GOTO EX$A31
  786.     LXI    H,ST$QT        ; HL <-- QUEUE TOP ADDRESS
  787. EX$A31    EQU    $
  788.     MOV    C,M        ; LSB OF FRAME SIZE
  789.     INX    H        ; ADVANCE POINTER
  790.     MOV    B,M        ; MSB OF FRAME SIZE
  791.     INX    H
  792.     MOV    E,M        ; LSB OF FRAME HEAD
  793.     INX    H
  794.     MOV    D,M        ; MSB OF FRAME HEAD
  795.     INX    H
  796.     SHLD    ST$QR        ; RECORD NEW POINTER
  797.     XCHG            ; HL <-- FRAME HEAD
  798.     SHLD    ST$BP        ; RECORD IT
  799.     LXI    H,STACT+2    ; HL <-- SYNC. XMTR PARAMETER POINTER
  800.     MOV    M,C        ; COPY LSB OF FRAME SIZE
  801.     INX    H        ; ADVANCE POINTER
  802.     MOV    M,B        ; COPY MSB OF FRAME SIZE
  803.     LXI    H,STACT        ; HL <-- SYNC. XMTR ACTIVATION COMMAND
  804.     CALL    SCMDOT        ; ISSUE COMMAND
  805. ;  SET WATCHDOG TIMER HERE (LETS GO FOR A DEFAULT VALUE INITIALLY)
  806.     LXI    H,WDVAL        ; HL <-- DEFAULT WATCHDOG TIMER
  807.     SHLD    IT$VAL        ; RECORD IT
  808.     MVI    A,1
  809.     STA    IT$FLG        ; ENABLE TIMER
  810.     INR    A        ; NEW STATE
  811.     STA    IT$STA        ; RECORD IT
  812.     JMP    EXEC
  813. ;    Queue empty, disable synchronous transmitter (deactivate RTS)
  814. EX$A32    EQU    $
  815.     LXI    H,DARTS        ; HL <-- DEACTIVATE RTS COMMAND
  816.     CALL    SCMDOT        ; ISSUE COMMAND
  817.     LDA    TVAL        ; A <-- SQUELCH TAIL TIMER VALUE
  818.     MOV    L,A        ; COPY VALUE TO L
  819.     XRA    A
  820.     MOV    H,A        ; EXTEND 16 BITS
  821.     SHLD    IT$VAL        ; RECORD IT
  822.     INR    A        ; A <-- 1
  823.     STA    IT$FLG        ; ACTIVATE TIMER
  824.     MVI    A,3        ; NEW STATE
  825.     STA    IT$STA        ; RECORD IT
  826.     JMP    EXEC
  827.  
  828.  
  829.  
  830.  
  831.  
  832. ;    Here for asynchronous transmitter frame completion
  833. EX$A4    EQU    $
  834.     MVI    B,0FFH-ATFC    ; B <-- FLAG MASK
  835.     DI            ; GATE INTERRUPTS MOMENTARILY
  836.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  837.     ANA    B        ; MASK OUT ATFC
  838.     STA    EA$FLG        ; WRITE FLAGS
  839.     EI            ; UNGATE
  840.     LDA    AT$QS        ; A <-- QUEUE SIZE
  841.     ORA    A
  842.     JZ    EXEC        ; IF (EMPTY QUEUE) GOTO EXEC
  843.     DCR    A        ; ELSE DECREMENT COUNT
  844.     STA    AT$QS        ; WRITE NEW COUNT
  845.     LHLD    AT$QR        ; HL <-- QUEUE READ POINTER
  846.     LXI    D,-AT$QB    ; DE <-- QUEUE BOTTOM ADDRESS
  847.     PUSH    H        ; PRESERVE HL
  848.     DAD    D
  849.     POP    H        ; RESTORE QUEUE POINTER
  850.     JNC    EX$A41        ; IF (NOT BOTTOM) GOTO EX$A41
  851.     LXI    H,AT$QT        ; HL <-- QUEUE TOP ADDRESS
  852. EX$A41    EQU    $
  853.     MOV    E,M        ; LSB OF FRAME HEAD
  854.     INX    H
  855.     MOV    D,M        ; MSB OF FRAME HEAD
  856.     INX    H
  857.     SHLD    AT$QR        ; RECORD NEW POINTER
  858.     XCHG            ; HL <-- FRAME HEAD
  859.     CALL    LATQ3        ; SEND FEND
  860.     JMP    EXEC
  861.  
  862.  
  863.  
  864.  
  865.  
  866. ;    Here for timer expiration
  867. EX$A5    EQU    $
  868.     MVI    B,0FFH-EXTI    ; B <-- FLAG MASK
  869.     DI            ; GATE INTERRUPTS MOMENTARILY
  870.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  871.     ANA    B        ; MASK OUT EXTI
  872.     STA    EA$FLG        ; WRITE FLAGS
  873.     EI            ; UNGATE
  874.     LDA    IT$STA        ; A <-- STATE OF INTERVAL TIMER
  875.     ORA    A
  876.     JZ    A5$S0        ; IF (SLOT-TIME DELAY) GOTO A5$S0
  877.     DCR    A
  878.     JZ    A5$S1        ; IF (RELAY DELAY) GOTO A5$S1
  879.     DCR    A
  880.     JZ    A5$S2        ; IF (WATCH DOG) GOTO A5$S2
  881.     DCR    A
  882.     JZ    A5$S3        ; IF (SQUELCH DELAY) GOTO A5$S3
  883.     JMP    EXEC        ; IGNORE INVALID STATES
  884.  
  885. ;    Slot-time is expired, if channel not busy, activate RTS
  886. A5$S0    EQU    $
  887.     LXI    H,RPA        ; HL <-- READ PORT A COMMAND
  888.     CALL    SCMDOT        ; ISSUE COMMAND
  889.     CALL    SRSLIN        ; READ RESULTS
  890.     ANI    MCD        ; MASK MODEM CARRIER DETECT
  891.     JNZ    EXEC        ; IF (CHANNEL BUSY) GOTO EXEC
  892. A5$S0A    EQU    $
  893.     LXI    H,SRDIS        ; HL <-- SYNC. RCVR DISABLE COMMAND
  894.     CALL    SCMDOT        ; ISSUE COMMAND
  895.     LXI    H,STRTS        ; HL <-- SYNC. XMTR RTS ENABLE COMMAND
  896.     CALL    SCMDOT        ; ISSUE COMMAND
  897.     LDA    RVAL        ; A <-- RELAY DELAY VALUE
  898.     MOV    L,A        ; COPY TO L
  899.     XRA    A
  900.     MOV    H,A        ; EXTEND 16 BITS
  901.     SHLD    IT$VAL        ; SET DELAY VALUE
  902.     INR    A        ; A <-- 1
  903.     STA    IT$FLG        ; ACTIVATE TIMER
  904.     STA    IT$STA        ; RECORD NEW STATE
  905.     LXI    H,ST$QS        ; HL <-- QUEUE SIZE POINTER
  906.     DCR    M        ; DECREMENT COUNT
  907.     LHLD    ST$QR        ; HL <-- QUEUE READ POINTER
  908.     LXI    D,-ST$QB    ; DE <-- QUEUE BOTTOM ADDRESS
  909.     PUSH    H
  910.     DAD    D
  911.     POP    H
  912.     JNC    A5$S0B        ; IF (NOT BOTTOM) GOTO A5$S0B
  913.     LXI    H,ST$QT        ; HL <-- QUEUE TOP ADDRESS
  914. A5$S0B    EQU    $
  915.     MOV    A,M        ; LSB OF FRAME SIZE
  916.     STA    STACT+2
  917.     INX    H        ; ADVANCE POINTER
  918.     MOV    A,M        ; MSB OF FRAME SIZE
  919.     STA    STACT+3
  920.     INX    H
  921.     MOV    E,M        ; LSB OF FRAME HEAD
  922.     INX    H
  923.     MOV    D,M        ; MSB OF FRAME HEAD
  924.     INX    H
  925.     SHLD    ST$QR        ; WRITE NEW POINTER
  926.     XCHG
  927.     SHLD    ST$BP        ; ESTABLISH NEW FRAME POINTER
  928.     JMP    EXEC
  929.  
  930. ;    Relay delay time expired, start data transmission
  931. A5$S1    EQU    $
  932.     LXI    H,STACT        ; HL <-- SYNC. XMTR ACTIVATION COMMAND
  933.     CALL    SCMDOT        ; ISSUE COMMAND
  934.     LXI    H,WDVAL        ; HL <-- WATCHDOG TIMER VALUE
  935.     SHLD    IT$VAL        ; RECORD IT
  936.     MVI    A,1
  937.     STA    IT$FLG        ; ACTIVATE TIMER
  938.     INR    A        ; NEW STATE
  939.     STA    IT$STA        ; RECORD IT
  940.     JMP    EXEC
  941.  
  942. ;    Watchdog timer expiration, kill the transmitter
  943. A5$S2    EQU    $
  944.     LXI    H,DARTS        ; HL <-- DEACTIVATE RTS COMMAND
  945.     CALL    SCMDOT        ; ISSUE COMMAND
  946.     JMP    INIT
  947.  
  948. ;    Squelch delay time expired, re-activate the sync. receiver
  949. A5$S3    EQU    $
  950.     LXI    H,SRACT        ; HL <-- SYNC. RCVR ACTIVATION COMMAND
  951.     CALL    SCMDOT        ; ISSUE COMMAND
  952.     JMP    EXEC
  953.  
  954.  
  955.  
  956.  
  957.  
  958. ;    Here when synchronous receiver is discarding a frame
  959. ;    because there are no available free cells.
  960. EX$A6    EQU    $
  961.     MVI    B,0FFH-SRDD    ; B <-- FLAG MASK
  962.     DI            ; GATE INTERRUPTS MOMENTARILY
  963.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  964.     ANA    B        ; MASK OUT SRDD
  965.     STA    EA$FLG        ; WRITE FLAGS
  966.     EI            ; UNGATE
  967.     LHLD    SR$HC        ; HL <-- FRAME HEAD
  968.     CALL    FCHN        ; FREE THIS CHAIN
  969.     LXI    H,SRDIS        ; HL <-- SYNC. RCVR DISABLE COMMAND
  970.     CALL    SCMDOT        ; ISSUE COMMAND
  971.     DI            ; GATE INTERRUPTS MOMENTARILY
  972.     CALL    GCELL        ; GET A FREE CELL
  973.     EI            ; UNGATE
  974.     XCHG            ; HL <-- CELL POINTER
  975.     SHLD    SR$BP        ; ESTABLISH NEW BUFFER POINTERS
  976.     SHLD    SR$HC
  977.     MVI    M,0        ; RESET FORWARD POINTER
  978.     INX    H        ; ADVANCE POINTER
  979.     MVI    M,0
  980.     LXI    H,SRACT        ; HL <-- SYNC. RCVR ACTIVATION COMMAND
  981.     CALL    SCMDOT        ; ISSUE COMMAND
  982.     XRA    A        ; NEW STATE (RECORDING DATA)
  983.     STA    SR$STA        ; RECORD IT
  984.     JMP    EXEC
  985.  
  986.  
  987.  
  988.  
  989.  
  990. ;    Here when asynchronous receiver is discarding a frame
  991. ;    because there are no available free cells.
  992. EX$A7    EQU    $
  993.     MVI    B,0FFH-ARDD    ; B <-- FLAG MASK
  994.     DI            ; GATE INTERRUPTS MOMENTARILY
  995.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  996.     ANA    B        ; MASK OUT ARDD
  997.     STA    EA$FLG        ; WRITE FLAGS
  998.     EI            ; UNGATE
  999.     LHLD    AR$HC        ; HL <-- FRAME HEAD
  1000.     CALL    FCHN        ; FREE THIS CHAIN
  1001.     MVI    A,ADTR+ARTS+OUT1 ; DTR, RTS, AND CD FOR HOST
  1002.     OUT    MCR        ; WRITE MODEM CONTROL REGISTER
  1003.     JMP    EXEC
  1004. ;    PAGE
  1005.  
  1006. ;    Queue management routines for synchronous & asynchronous output
  1007.  
  1008. ;    Link a frame to the synchronous transmit queue
  1009. LSTQ    EQU    $
  1010.     XCHG            ; DE <-- ADDRESS OF FRAME
  1011.     LHLD    ST$QW        ; HL <-- QUEUE WRITE POINTER
  1012.     MOV    M,C        ; LSB OF FRAME SIZE
  1013.     INX    H        ; ADVANCE POINTER
  1014.     MOV    M,B        ; MSB OF FRAME SIZE
  1015.     INX    H
  1016.     MOV    M,E        ; LSB OF FRAME HEAD
  1017.     INX    H
  1018.     MOV    M,D        ; MSB OF FRAME HEAD
  1019.     INX    H        ; HL <-- NEXT QUEUE ENTRY
  1020.     LXI    D,-ST$QB    ; DE <-- QUEUE BOTTOM ADDRESS
  1021.     PUSH    H        ; PRESERVE HL
  1022.     DAD    D
  1023.     POP    H        ; RESTORE QUEUE POINTER
  1024.     JNC    LSTQ1        ; IF (NOT BOTTOM) GOTO LSTQ1
  1025.     LXI    H,ST$QT        ; HL <-- QUEUE TOP ADDRESS
  1026. LSTQ1    EQU    $
  1027.     SHLD    ST$QW        ; WRITE NEW QUEUE POINTER
  1028.     LXI    H,ST$QS        ; HL <-- QUEUE SIZE POINTER
  1029.     INR    M        ; INCREMENT QUEUE SIZE
  1030.     RET
  1031.  
  1032.  
  1033.  
  1034.  
  1035.  
  1036. ;    Link a frame to the asynchronous transmit queue
  1037. LATQ    EQU    $
  1038.     LDA    AT$QS        ; A <-- QUEUE SIZE
  1039.     ORA    A
  1040.     JNZ    LATQ1        ; IF (QUEUED FRAMES) GOTO LATQ1
  1041.     LDA    AT$STA        ; A <-- STATE OF ASYNC. TRANSMITTER
  1042.     CPI    0FFH
  1043.     JZ    LATQ3        ; IF (XMTR INACTIVE) GOTO LATQ3
  1044. LATQ1    EQU    $
  1045.     XCHG            ; DE <-- ADDRESS OF FRAME
  1046.     LHLD    AT$QW        ; HL <-- QUEUE WRITE POINTER
  1047.     MOV    M,E        ; LSB OF FRAME HEAD
  1048.     INX    H        ; ADVANCE POINTER
  1049.     MOV    M,D        ; MSB OF FRAME HEAD
  1050.     INX    H        ; HL <-- NEXT QUEUE ENTRY
  1051.     LXI    D,-AT$QB    ; DE <-- QUEUE BOTTOM ADDRESS
  1052.     PUSH    H        ; PRESERVE HL
  1053.     DAD    D
  1054.     POP    H        ; RESTORE QUEUE POINTER
  1055.     JNC    LATQ2        ; IF (NOT BOTTOM) GOTO LATQ2
  1056.     LXI    H,AT$QT        ; HL <-- QUEUE TOP ADDRESS
  1057. LATQ2    EQU    $
  1058.     SHLD    AT$QW        ; WRITE NEW POINTER
  1059.     LXI    H,AT$QS        ; HL <-- QUEUE SIZE POINTER
  1060.     INR    M        ; INCREMENT QUEUE SIZE
  1061.     RET
  1062. ;    Queue is empty and asynchronous transmitter is
  1063. ;    inactive.  Don't queue this entry, just send it out.
  1064. LATQ3    EQU    $
  1065.     SHLD    AT$BP        ; ESTABLISH NEW POINTER
  1066.     MVI    A,FEND        ; A <-- FEND
  1067.     OUT    THR        ; WRITE TRANSMIT HOLDING REGISTER
  1068.     MVI    A,4        ; NEW STATE (OPENING FRAME)
  1069.     STA    AT$STA        ; RECORD IT
  1070.     MVI    A,ERI+ETI+ELI+EMI ; 8250 INTERRUPT ENABLE FLAGS
  1071.     OUT    IER        ; WRITE INTERRUPT ENABLE REGISTER
  1072.     RET
  1073. ;    PAGE
  1074.  
  1075. ;    Buffer management routines
  1076.  
  1077. ;    Allocate a free cell
  1078. GCELL    EQU    $
  1079.     LHLD    FL$HC        ; HL <-- HEAD CELL ON FREE LIST
  1080.     MOV    A,H        ; MSB OF ADDRESS
  1081.     ORA    L        ; LSB OF ADDRESS
  1082.     JZ    GC$EL        ; IF (EMPTY LIST) GOTO GC$EL
  1083.     XCHG            ; DE <-- FREE CELL
  1084.     LXI    H,FL$HC        ; HL <-- HEAD CELL POINTER
  1085.     LDAX    D        ; A <-- LSB OF NEXT FREE CELL
  1086.     MOV    M,A        ; COPY TO FL$HC
  1087.     INX    D        ; ADVANCE POINTERS
  1088.     INX    H
  1089.     LDAX    D        ; A <-- MSB OF NEXT FREE CELL
  1090.     MOV    M,A        ; COPY TO FL$HC
  1091.     DCX    D        ; RESET FREE CELL POINTER
  1092. GC$EL    EQU    $
  1093.     RET
  1094.  
  1095. ;    Attach a cell to the free list
  1096. FCELL    EQU    $
  1097.     LXI    H,FL$HC        ; HL <-- HEAD CELL POINTER
  1098.     MOV    C,M        ; C <-- LSB OF FIRST CELL
  1099.     MOV    M,E        ; UPDATE LSB OF FL$HC
  1100.     INX    H        ; ADVANCE POINTER
  1101.     MOV    B,M        ; B <-- MSB OF FIRST CELL
  1102.     MOV    M,D        ; UPDATE MSB OF FL$HC
  1103.     XCHG            ; HL <-- RELEASED CELL
  1104.     MOV    E,M        ; E <-- LSB OF NEXT CELL
  1105.     MOV    M,C        ; COPY LSB OF OLD HC TO NEW
  1106.     INX    H        ; ADVANCE POINTER
  1107.     MOV    D,M        ; D <-- MSB OF NEXT CELL
  1108.     MOV    M,B        ; COPY MSB OF OLD HC TO NEW
  1109.     INX    H        ; ADVANCE POINTER
  1110.     MVI    M,0        ; RESET NBYTE
  1111.     INX    H
  1112.     MVI    M,0        ; RESET NREAD
  1113.     XCHG            ; HL <-- NEXT CELL IN CHAIN
  1114.     RET
  1115.  
  1116. ;    Attach a chain of cells to the free list
  1117. FCHN    EQU    $
  1118.     XCHG            ; DE <-- CELL TO BE RELEASED
  1119.     DI            ; GATE INTERRUPTS MOMENTARILY
  1120.     CALL    FCELL        ; FREE IT UP
  1121.     EI            ; UNGATE
  1122.     MOV    A,H        ; MSB OF FORWARD POINTER FROM CELL
  1123.     ORA    L        ; LSB OF SAME
  1124.     JNZ    FCHN        ; IF (MORE CELLS) GOTO FCHN
  1125.     RET
  1126. ;    PAGE
  1127.  
  1128. ;    Extract a character from the buffer referenced by HL
  1129. GCHAR    EQU    $
  1130.     PUSH    H        ; PRESERVE HL
  1131.     INX    H        ; SKIP FORWARD POINTER
  1132.     INX    H
  1133.     MOV    A,M        ; A <-- NBYTES
  1134.     INX    H        ; ADVANCE POINTER
  1135.     SUB    M        ; CHECK NREAD
  1136.     JZ    GC$BE        ; IF (BUFFER EXHAUSTED) GOTO GC$BE
  1137.     PUSH    D        ; PRESERVE DE
  1138.     INR    M        ; INCREMENT NREAD
  1139.     MOV    E,M        ; E <-- NREAD
  1140.     XRA    A
  1141.     MOV    D,A        ; EXTEND 16 BITS
  1142.     DAD    D        ; HL <-- HL + DE
  1143.     INR    A        ; RESET 'Z' FLAG
  1144.     MOV    A,M        ; A <-- CHARACTER
  1145.     POP    D        ; RESTORE DE
  1146.     POP    H        ; RESTORE HL
  1147.     RET
  1148. ;    Follow chain to next buffer
  1149. GC$BE    EQU    $
  1150.     POP    H        ; RESTORE HL
  1151.     PUSH    D        ; PRESERVE DE & BC
  1152.     PUSH    B
  1153.     XCHG            ; DE <-- BUFFER POINTER
  1154.     CALL    FCELL        ; RELEASE THIS CELL
  1155.     POP    B        ; RESTORE BC & DE
  1156.     POP    D
  1157.     MOV    A,H        ; MSB OF NEXT CELL IN CHAIN
  1158.     ORA    L        ; LSB OF SAME
  1159.     JNZ    GCHAR        ; IF (GOOD BUFFER) GOTO GCHAR
  1160.     RET            ; ELSE RETURN WITH 'Z' FLAG SET
  1161.  
  1162. ;    Stuff a character into the buffer referenced by HL
  1163. PCHAR    EQU    $
  1164.     PUSH    D        ; PRESERVE DE
  1165.     PUSH    PSW        ; PRESERVE PSW (CHARACTER)
  1166.     INX    H        ; SKIP FORWARD POINTER
  1167.     INX    H
  1168.     MVI    A,124        ; A <-- BUFFER LIMIT
  1169.     SUB    M        ; A <-- 124 - NBYTES
  1170.     CZ    PC$NB        ; IF (NEED BUFFER) CALL PC$NB
  1171.     PUSH    H        ; PRESERVE HL (BUFFER POINTER)
  1172.     INR    M        ; INCREMENT NBYTES
  1173.     MOV    E,M        ; E <-- NBYTES
  1174.     XRA    A
  1175.     MOV    D,A        ; EXTEND 16 BITS
  1176.     INX    H        ; SKIP NBYTES
  1177.     DAD    D        ; HL <-- HL + DE
  1178.     POP    D        ; RESTORE POINTER
  1179.     POP    PSW        ; RESTORE CHARACTER
  1180.     MOV    M,A        ; COPY CHARACTER TO BUFFER
  1181.     XCHG            ; HL <-- ORIGINAL POINTER
  1182.     DCX    H        ; ADJUST POINTER
  1183.     DCX    H
  1184.     POP    D        ; RESTORE DE
  1185.     XRA    A
  1186.     INR    A        ; RESET 'Z' FLAG
  1187.     RET
  1188. ;    Here if PCHAR needs a new buffer
  1189. PC$NB    EQU    $
  1190.     PUSH    H        ; PRESERVE HL
  1191.     CALL    GCELL        ; FREE CELL POINTER TO DE
  1192.     POP    H        ; RESTORE HL
  1193.     JZ    PC$BF        ; IF (BUFFERS FULL) GOTO PC$BF
  1194.     DCX    H
  1195.     MOV    M,D        ; COPY MSB TO PREVIOUS CELL
  1196.     DCX    H        ; ADVANCE POINTER
  1197.     MOV    M,E        ; COPY LSB TO PREVIOUS CELL
  1198.     XCHG            ; HL <-- NEW BUFFER POINTER
  1199.     MVI    M,0        ; RESET FORWARD POINTER
  1200.     INX    H        ; ADVANCE POINTER
  1201.     MVI    M,0
  1202.     INX    H
  1203.     RET
  1204. ;    Here if free cell not available
  1205. PC$BF    EQU    $
  1206.     POP    PSW        ; PURGE RETURN ADDRESS FROM STACK
  1207.     POP    PSW        ; RESTORE CHARACTER
  1208.     POP    D        ; RESTORE DE
  1209.     XRA    A        ; SET 'Z' FLAG
  1210.     RET
  1211. ;    PAGE
  1212.  
  1213. ;    Asynchronous Interrupt Response Code
  1214.  
  1215. AIRC    EQU    $
  1216.     PUSH    PSW        ; SAVE PROGRAM STATUS WORD
  1217.     IN    IIR        ; READ INTERRUPT IDENTIFICATION REG.
  1218.     RAR            ; RIGHT JUSTIFY ID BITS
  1219.     ANI    00000011B    ; MASK
  1220.     JZ    IRC$AM        ; IF (MODEM STATUS) GOTO IRC$AM
  1221.     DCR    A
  1222.     JZ    IRC$AT        ; IF (XMTR EMPTY) GOTO IRC$AT
  1223.     DCR    A
  1224.     JZ    IRC$AR        ; IF (DATA READY) GOTO IRC$AR
  1225.  
  1226.  
  1227.  
  1228.  
  1229.  
  1230. ;    Here for line status interrupt
  1231. IRC$AL    EQU    $
  1232.     IN    LSR        ; READ LINE STATUS REGISTER
  1233.     ANI    BI        ; MASK BREAK INTERRUPT
  1234. ;    Treat overrun, parity, framing errors as data ready
  1235.     JZ    IRC$AR        ; IF (NOT BI) GOTO IRC$AR
  1236.     IN    RBR        ; FLUSH NULL FROM BUFFER
  1237.     POP    PSW        ; RESTORE PSW
  1238.     EI            ; UNGATE
  1239.     RET            ; RETURN FROM INTERRUPT
  1240.  
  1241.  
  1242.  
  1243.  
  1244.  
  1245. ;    Here for modem status interrupt
  1246. IRC$AM    EQU    $
  1247.     IN    MSR        ; READ MODEM STATUS
  1248.     PUSH    PSW        ; SAVE STATUS
  1249.     ANI    DCTS+DDSR    ; MASK SOURCE BITS OF INTEREST
  1250.     RAR
  1251.     RAR
  1252.     JM    AM$1        ; IF (DELTA CTS) GOTO AM$1
  1253.     JC    INIT        ; IF (HOST LOST) GOTO INIT
  1254. ;    Ignore other sources of this interrupt
  1255.     POP    PSW        ; REMOVE STATUS FROM STACK
  1256.     POP    PSW
  1257.     EI
  1258.     RET            ; RETURN FROM INTERRUPT
  1259. ;    Here if Clear-To-Send has changed state
  1260. AM$1    EQU    $
  1261.     POP    PSW        ; FETCH MODEM STATUS FROM STACK
  1262.     ANI    TCTS        ; MASK TERMINAL CLEAR-TO-SEND STATUS
  1263.     JNZ    AM$2        ; IF (CLEAR-TO-SEND) GOTO AM$2
  1264. ;    Host has full buffer or something, stop sending
  1265.     MVI    A,ERI+ELI+EMI    ; INTERRUPT ENABLE FLAGS
  1266.     OUT    IER        ; WRITE INTERRUPT ENABLE REGISTER
  1267.     POP    PSW
  1268.     EI
  1269.     RET            ; RETURN FROM INTERRUPT
  1270. ;    Host is now ready to receive data again
  1271. AM$2    EQU    $
  1272.     LDA    AT$STA        ; A <-- STATE OF TRANSMITTER
  1273.     CPI    0FFH
  1274.     JZ    AM$3        ; IF (INACTIVE) GOTO AM$3
  1275.     MVI    A,ERI+ETI+ELI+EMI ; INTERRUPT ENABLE FLAGS
  1276.     OUT    IER        ; WRITE INTERRUPT ENABLE REGISTER
  1277. AM$3    EQU    $
  1278.     POP    PSW
  1279.     EI
  1280.     RET            ; RETURN FROM INTERRUPT
  1281.  
  1282.  
  1283.  
  1284.  
  1285.  
  1286. ;    Here for asynchronous transmit interrupt
  1287. IRC$AT    EQU    $
  1288.     LDA    AT$STA        ; A <-- STATE OF TRANSMITTER
  1289.     ORA    A
  1290.     JZ    AT$S0        ; IF (NOT ESCAPED) GOTO AT$S0
  1291.     DCR    A
  1292.     JZ    AT$S1        ; IF (SENDING TFESC) GOTO AT$S1
  1293.     DCR    A
  1294.     JZ    AT$S2        ; IF (SENDING TFEND) GOTO AT$S2
  1295.     DCR    A
  1296.     JZ    AT$S3        ; IF (END OF FRAME) GOTO AT$S3
  1297.     DCR    A
  1298.     JZ    AT$S4        ; IF (OPENING FRAME) GOTO AT$S4
  1299.     JMP    RST1+1        ; IGNORE INACTIVE STATE
  1300.  
  1301. ;    Here for normal data transmission (not currently escaped)
  1302. AT$S0    EQU    $
  1303.     PUSH    H        ; PRESERVE HL
  1304.     LHLD    AT$BP        ; HL <-- BUFFER POINTER
  1305.     CALL    GCHAR        ; MOVE NEXT CHARACTER TO A
  1306.     SHLD    AT$BP        ; SAVE UPDATED POINTER
  1307.     POP    H        ; RESTORE HL
  1308.     JZ    AT$S0S3        ; IF (END OF FRAME) GOTO AT$S0S3
  1309.     CPI    FESC
  1310.     JZ    AT$S0S1        ; IF (CHAR = FESC) GOTO AT$S0S1
  1311.     CPI    FEND
  1312.     JZ    AT$S0S2        ; IF (CHAR = FEND) GOTO AT$S0S2
  1313.     OUT    THR        ; WRITE CHARACTER
  1314.     POP    PSW
  1315.     EI
  1316.     RET            ; RETURN FROM INTERRUPT
  1317. ;    Send FESC and change state to 1
  1318. AT$S0S1    EQU    $
  1319.     OUT    THR        ; WRITE FESC
  1320.     MVI    A,1        ; NEW STATE
  1321.     STA    AT$STA        ; RECORD NEW STATE
  1322.     POP    PSW
  1323.     EI
  1324.     RET            ; RETURN FROM INTERRUPT
  1325. ;    Send FESC and change state to 2
  1326. AT$S0S2    EQU    $
  1327.     MVI    A,FESC        ; A <-- FESC
  1328.     OUT    THR        ; WRITE
  1329.     MVI    A,2        ; NEW STATE
  1330.     STA    AT$STA        ; RECORD NEW STATE
  1331.     POP    PSW
  1332.     EI
  1333.     RET            ; RETURN FROM INTERRUPT
  1334. ;    Send FEND and change state to 3
  1335. AT$S0S3    EQU    $
  1336.     MVI    A,FEND        ; A <-- FEND
  1337.     OUT    THR        ; WRITE
  1338.     MVI    A,3        ; NEW STATE
  1339.     STA    AT$STA        ; RECORD NEW STATE
  1340.     POP    PSW
  1341.     EI
  1342.     RET            ; RETURN FROM INTERRUPT
  1343.  
  1344. ;    Send TFESC (FESC was last character sent)
  1345. AT$S1    EQU    $
  1346.     MVI    A,TFESC        ; A <-- TFESC
  1347.     OUT    THR        ; WRITE
  1348.     XRA    A        ; NEW STATE (NOT ESCAPED)
  1349.     STA    AT$STA        ; RECORD NEW STATE
  1350.     POP    PSW
  1351.     EI
  1352.     RET            ; RETURN FROM INTERRUPT
  1353.  
  1354. ;    Send TFEND (FESC was last character sent)
  1355. AT$S2    EQU    $
  1356.     MVI    A,TFEND        ; A <-- TFEND
  1357.     OUT    THR        ; WRITE
  1358.     XRA    A        ; NEW STATE (NOT ESCAPED)
  1359.     STA    AT$STA        ; RECORD NEW STATE
  1360.     POP    PSW
  1361.     EI
  1362.     RET            ; RETURN FROM INTERRUPT
  1363.  
  1364. ;    Here for end of frame transmission - FEND already sent
  1365. AT$S3    EQU    $
  1366.     MVI    A,ERI+ELI+EMI    ; RCVR, LINE, AND MODEM ENABLE FLAGS
  1367.     OUT    IER        ; WRITE INTERRUPT ENABLE REGISTER
  1368.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  1369.     ORI    ATFC        ; SET ASYNC. XMTR FRAME COMPLETE
  1370.     STA    EA$FLG        ; WRITE FLAGS
  1371.     MVI    A,0FFH        ; NEW STATE (ASYNC. XMTR DISABLED)
  1372.     STA    AT$STA        ; RECORD IT
  1373.     POP    PSW
  1374.     EI
  1375.     RET
  1376.  
  1377. ;    Here for opening frame, send data frame control byte
  1378. AT$S4    EQU    $
  1379.     XRA    A        ; A <-- 0
  1380.     OUT    THR        ; WRITE CONTROL BYTE
  1381.     STA    AT$STA        ; ALSO IS OUR NEW STATE
  1382.     POP    PSW
  1383.     EI
  1384.     RET
  1385.  
  1386.  
  1387.  
  1388.  
  1389. ;    Here for asynchronous receive interrupt
  1390. IRC$AR    EQU    $
  1391.     LDA    AR$STA        ; A <-- STATE OF RECEIVER
  1392.     ORA    A
  1393.     JZ    AR$S0        ; IF (EXPECTING DATA) GOTO AR$S0
  1394.     DCR    A
  1395.     JZ    AR$S1        ; IF (ESCAPED) GOTO AR$S1
  1396.     DCR    A
  1397.     JZ    AR$S2        ; IF (EXPECTING COMMAND) GOTO AR$S2
  1398.     DCR    A
  1399.     JZ    AR$S3        ; IF (EXPECTING P-VALUE) GOTO AR$S3
  1400.     DCR    A
  1401.     JZ    AR$S4        ; IF (EXPECTING S-VALUE) GOTO AR$S4
  1402.     DCR    A
  1403.     JZ    AR$S5        ; IF (EXPECTING T-VALUE) GOTO AR$S5
  1404.     DCR    A
  1405.     JZ    AR$S6        ; IF (EXPECTING TXDELAY) GOTO AR$S6
  1406.  
  1407. ;    Here if waiting for FEND to begin a new frame
  1408. AR$S7    EQU    $
  1409.     IN    RBR        ; READ CHARACTER
  1410.     CPI    FEND
  1411.     JNZ    RST1+1        ; IF (NOT FEND) RETURN FROM INTERRUPT
  1412.     MVI    A,2        ; NEW STATE
  1413.     STA    AR$STA        ; RECORD NEW STATE
  1414.     POP    PSW
  1415.     EI
  1416.     RET            ; RETURN FROM INTERRUPT
  1417.  
  1418. ;    Here if expecting frame data
  1419. AR$S0    EQU    $
  1420.     IN    RBR        ; READ CHARACTER
  1421.     CPI    FESC
  1422.     JZ    AR$S0S1        ; IF (DATA = FESC) GOTO AR$S0S1
  1423.     CPI    FEND
  1424.     JZ    AR$S0S2        ; IF (DATA = FEND) GOTO AR$S0S2
  1425.     PUSH    H        ; PRESERVE HL
  1426.     LHLD    AR$BP        ; HL <-- BUFFER POINTER
  1427.     CALL    PCHAR        ; STORE CHARACTER
  1428.     JZ    AR$S0S7        ; IF (BUFFERS FULL) GOTO AR$S0A
  1429.     SHLD    AR$BP        ; RECORD NEW POINTER
  1430.     LHLD    AR$FSZ        ; HL <-- FRAME SIZE
  1431.     INX    H        ; INCREMENT COUNT
  1432.     SHLD    AR$FSZ        ; RECORD IT
  1433.     POP    H        ; RESTORE HL
  1434.     POP    PSW
  1435.     EI
  1436.     RET            ; RETURN FROM INTERRUPT
  1437. ;    Here we deal with a serious problem.  We are in the middle
  1438. ;    of a frame and filled our current buffer, but alas, there
  1439. ;    are no free cells to allocate.  Return all buffers in this
  1440. ;    frame to the free cell list and hope we recover.
  1441. AR$S0S7    EQU    $
  1442. AR$S1S7    EQU    $
  1443.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  1444.     ORI    ARDD        ; ASYNC. RECEIVER DISCARDING DATA
  1445.     STA    EA$FLG        ; SAVE UPDATED FLAGS
  1446.     MVI    A,ADTR+OUT1    ; DTR & CD, NO RTS
  1447.     OUT    MCR        ; WRITE MODEM CONTROL REGISTER
  1448.     POP    H        ; RESTORE HL
  1449. ;    Here we just change state to wait for the next incoming
  1450. ;    frame and hope by then that we have recovered some cells.
  1451. AR$S2S7    EQU    $
  1452.     MVI    A,7        ; NEW STATE
  1453.     STA    AR$STA        ; RECORD NEW STATE
  1454.     POP    PSW
  1455.     EI
  1456.     RET            ; RETURN FROM INTERRUPT
  1457. ;    FESC was just detected. Change state to 1 and see what follows.
  1458. AR$S0S1    EQU    $
  1459.     MVI    A,1        ; NEW STATE
  1460.     STA    AR$STA        ; RECORD IT
  1461.     POP    PSW
  1462.     EI
  1463.     RET            ; RETURN FROM INTERRUPT
  1464. ;    FEND was just detected.  Move frame to synch. transmit queue.
  1465. AR$S0S2    EQU    $
  1466.     PUSH    H        ; PRESERVE HL
  1467.     LHLD    AR$HC        ; HL <-- HEAD CELL POINTER
  1468.     SHLD    AR$FH        ; SAVE POINTER FOR EXEC
  1469.     LHLD    AR$FSZ        ; HL <-- FRAME SIZE
  1470.     SHLD    AR$FS        ; SAVE FOR EXECUTIVE
  1471.     MVI    A,2        ; NEW STATE
  1472.     STA    AR$STA        ; RECORD IT
  1473.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  1474.     ORI    ARFC        ; ASYNC. RECEIVER FRAME COMPLETE
  1475.     STA    EA$FLG        ; SAVE UPDATED FLAGS
  1476.     MVI    A,ADTR+OUT1    ; DTR & CD, NO RTS
  1477.     OUT    MCR        ; WRITE MODEM CONTROL REGISTER
  1478.     POP    H        ; RESTORE HL
  1479.     POP    PSW
  1480.     EI
  1481.     RET            ; RETURN FROM INTERRUPT
  1482.  
  1483. ;    This character follows an FESC, must be TFESC or TFEND
  1484. AR$S1    EQU    $
  1485.     XRA    A        ; NEW STATE
  1486.     STA    AR$STA        ; RECORD IT
  1487.     IN    RBR        ; READ CHARACTER
  1488.     CPI    TFESC
  1489.     JZ    AR$S1A        ; IF (DATA = TFESC) GOTO AR$S1A
  1490.     CPI    TFEND
  1491.     JNZ    RST1+1        ; IF (DATA <> TFEND) RETURN FROM INT.
  1492. ;    Character was TFEND.  Translate it.
  1493.     MVI    A,FEND        ; A <-- FEND
  1494.     JMP    AR$S1B        ; STORE IT
  1495. ;    Character was TFESC.  Translate it.
  1496. AR$S1A    EQU    $
  1497.     MVI    A,FESC        ; A <-- FESC
  1498. AR$S1B    EQU    $
  1499.     PUSH    H        ; PRESERVE HL
  1500.     LHLD    AR$BP        ; HL <-- BUFFER POINTER
  1501.     CALL    PCHAR        ; STORE CHARACTER
  1502.     JZ    AR$S1S7        ; IF (BUFFERS FULL) GOTO AR$S1S7
  1503.     SHLD    AR$BP        ; RECORD NEW POINTER
  1504.     LHLD    AR$FSZ        ; HL <-- FRAME SIZE
  1505.     INX    H        ; INCREMENT COUNT
  1506.     SHLD    AR$FSZ        ; RECORD IT
  1507.     POP    H        ; RESTORE HL
  1508.     POP    PSW
  1509.     EI
  1510.     RET            ; RETURN FROM INTERRUPT
  1511.  
  1512. ;    Last character seen was FEND.  Look for frame command.
  1513. AR$S2    EQU    $
  1514.     IN    RBR        ; READ CHARACTER
  1515.     CPI    FEND
  1516.     JZ    RST1+1        ; RETURN FROM INTERRUPT
  1517.     ORA    A
  1518.     JZ    AR$S2S0        ; IF (DATA FRAME) GOTO AR$S2S0
  1519.     DCR    A
  1520.     JZ    AR$S2A        ; IF (R COMMAND) GOTO AR$S2A
  1521.     DCR    A
  1522.     JZ    AR$S2B        ; IF (P COMMAND) GOTO AR$S2B
  1523.     DCR    A
  1524.     JZ    AR$S2C        ; IF (S COMMAND) GOTO AR$S2C
  1525.     DCR    A
  1526.     JZ    AR$S2D        ; IF (T COMMAND) GOTO AR$S2D
  1527.     JMP    AR$S2S7        ; BOGUS COMMAND, WAIT FOR FEND
  1528. ;    Here if TxDelay value to follow
  1529. AR$S2A    EQU    $
  1530.     MVI    A,6        ; NEW STATE
  1531.     STA    AR$STA        ; RECORD IT
  1532.     POP    PSW
  1533.     EI
  1534.     RET            ; RETURN FROM INTERRUPT
  1535. ;    Here if Persistence value to follow
  1536. AR$S2B    EQU    $
  1537.     MVI    A,3
  1538.     STA    AR$STA    
  1539.     POP    PSW
  1540.     EI
  1541.     RET
  1542. ;    Here if Slot-time value to follow
  1543. AR$S2C    EQU    $
  1544.     MVI    A,4
  1545.     STA    AR$STA    
  1546.     POP    PSW
  1547.     EI
  1548.     RET
  1549. ;    Here if Squelch-delay value to follow
  1550. AR$S2D    EQU    $
  1551.     MVI    A,5
  1552.     STA    AR$STA    
  1553.     POP    PSW
  1554.     EI
  1555.     RET
  1556. ;    Here when data to follow
  1557. AR$S2S0    EQU    $
  1558.     PUSH    H        ; PRESERVE HL
  1559.     CALL    GCELL        ; GET A FREE CELL
  1560.     JZ    AR$S2S7        ; IF (BUFFERS FULL) GOTO AR$S0S7
  1561.     XCHG            ; HL <-- CELL POINTER
  1562.     SHLD    AR$BP        ; ESTABLISH NEW BUFFER POINTERS
  1563.     SHLD    AR$HC
  1564.     MVI    M,0        ; RESET FORWARD POINTER
  1565.     INX    H        ; ADVANCE POINTER
  1566.     MVI    M,0
  1567.     LXI    H,0        ; HL <-- 0
  1568.     SHLD    AR$FSZ        ; RESET FRAME SIZE
  1569.     POP    H        ; RESTORE HL
  1570.     XRA    A        ; NEW STATE
  1571.     STA    AR$STA        ; RECORD IT
  1572.     POP    PSW
  1573.     EI
  1574.     RET            ; RETURN FROM INTERRUPT
  1575.  
  1576. ;    Load a persistence value
  1577. AR$S3    EQU    $
  1578.     IN    RBR
  1579.     STA    PVAL
  1580.     MVI    A,2
  1581.     STA    AR$STA    
  1582.     POP    PSW
  1583.     EI
  1584.     RET
  1585.  
  1586. ;    Load a slot-time value
  1587. AR$S4    EQU    $
  1588.     IN    RBR
  1589.     STA    SVAL
  1590.     MVI    A,2
  1591.     STA    AR$STA    
  1592.     POP    PSW
  1593.     EI
  1594.     RET
  1595.  
  1596. ;    Load a squelch-delay value
  1597. AR$S5    EQU    $
  1598.     IN    RBR
  1599.     STA    TVAL
  1600.     MVI    A,2
  1601.     STA    AR$STA    
  1602.     POP    PSW
  1603.     EI
  1604.     RET
  1605.  
  1606. ;    Load a Tx relay delay value
  1607. AR$S6    EQU    $
  1608.     IN    RBR
  1609.     STA    RVAL
  1610.     MVI    A,2
  1611.     STA    AR$STA    
  1612.     POP    PSW
  1613.     EI
  1614.     RET
  1615. ;    PAGE
  1616.  
  1617. ;    Synchronous Transmitter Interrupt Response Code
  1618.  
  1619. STIRC    EQU    $
  1620.     PUSH    PSW        ; PRESERVE PROGRAM STATUS WORD
  1621.     PUSH    H        ; SAME WITH HL
  1622.     IN    STAT73        ; READ STATUS
  1623.     ANI    TXIRA
  1624.     JNZ    ST$CI        ; IF (END-OF-FRAME) GOTO ST$CI
  1625. ;    Here if transmitter waiting for data
  1626.     LHLD    ST$BP        ; HL <-- BUFFER POINTER
  1627.     CALL    GCHAR        ; MOVE NEXT CHARACTER TO A
  1628.     OUT    TXDR73        ; WRITE CHARACTER
  1629.     SHLD    ST$BP        ; SAVE UPDATED POINTER
  1630.     POP    H        ; RESTORE HL
  1631.     POP    PSW
  1632.     EI
  1633.     RET            ; RETURN FROM INTERRUPT
  1634.  
  1635. ;    Here for frame completion interrupt
  1636. ST$CI    EQU    $
  1637.     IN    TXIR73        ; READ RESULTS
  1638.     STA    ST$FR        ; SAVE RESULTS POINTER
  1639.     PUSH    D        ; PRESERVE DE
  1640.     LHLD    ST$BP        ; HL <-- CURRENT BUFFER POINTER
  1641.     XCHG            ; MOVE POINTER TO DE
  1642.     CALL    FCELL        ; FREE THIS CELL
  1643.     POP    D        ; RESTORE DE
  1644.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  1645.     ORI    STFC        ; SYNC. TRANSMITTER FRAME COMPLETE
  1646.     STA    EA$FLG        ; SAVE UPDATED FLAGS
  1647.     POP    H        ; RESTORE HL
  1648.     POP    PSW
  1649.     EI
  1650.     RET            ; RETURN FROM INTERRUPT
  1651. ;    PAGE
  1652.  
  1653. ;    Synchronous Receiver Interrupt Response Code
  1654.  
  1655. SRIRC    EQU    $
  1656.     PUSH    PSW        ; PRESERVE PROGRAM STATUS WORD
  1657.     LDA    SR$STA        ; A <-- STATE OF SYNC. RECEIVER
  1658.     ORA    A
  1659.     JNZ    SR$S1        ; IF (DISCARDING DATA) GOTO SR$S1
  1660.  
  1661. ;    Here if synchronous receiver state 0, recording data
  1662. SR$S0    EQU    $
  1663.     PUSH    H        ; PRESERVE HL
  1664.     IN    STAT73        ; READ STATUS
  1665.     ANI    RXIRA
  1666.     JNZ    SR$CI        ; IF (END-OF-FRAME) GOTO SR$CI
  1667. ;    Here if receiver has data to unload
  1668.     IN    RXDR73        ; READ CHARACTER
  1669.     LHLD    SR$BP        ; HL <-- BUFFER POINTER
  1670.     CALL    PCHAR        ; COPY CHARACTER TO BUFFER
  1671.     JZ    SR$BF        ; IF (BUFFERS FULL) GOTO SR$BF
  1672.     SHLD    SR$BP        ; SAVE UPDATED POINTER
  1673.     POP    H        ; RESTORE HL
  1674.     POP    PSW
  1675.     EI
  1676.     RET            ; RETURN FROM INTERRUPT
  1677.  
  1678. ;    Here for frame completion interrupt
  1679. SR$CI    EQU    $
  1680.     IN    RXIR73        ; READ FRAME STATUS
  1681.     STA    SR$FR        ; SAVE IT FOR EXEC
  1682.     PUSH    B        ; PRESERVE BC
  1683. SR$CIA    EQU    $
  1684.     IN    STAT73        ; READ STATUS
  1685.     MOV    B,A        ; COPY STATUS TO B
  1686.     ANI    RINTP
  1687.     JZ    SR$CIB        ; IF (RESULTS COMPLETE) GOTO SR$CIB
  1688.     MOV    A,B        ; RESTORE STATUS
  1689.     ANI    RXIRA
  1690.     JZ    SR$CIA        ; IF (NO RESULTS) GOTO SR$CIA
  1691. ;    Ready to read one byte of results code
  1692.     IN    RXIR73        ; READ RESULTS
  1693.     JMP    SR$CIA        ; WAIT FOR MORE, IF ANY
  1694. ;    Results are now complete
  1695. SR$CIB    EQU    $
  1696.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  1697.     ORI    SRFC        ; SYNC. RECEIVER FRAME COMPLETE
  1698.     STA    EA$FLG        ; SAVE UPDATED FLAGS
  1699.     POP    B        ; RESTORE BC
  1700.     POP    H        ; RESTORE HL
  1701.     POP    PSW
  1702.     EI
  1703.     RET            ; RETURN FROM INTERRUPT
  1704. ;    Again we must deal with being in the middle of a frame
  1705. ;    with no available free cells to continue.  Release the
  1706. ;    cells for this frame and cease reception till we recover.
  1707. SR$BF    EQU    $
  1708.     MVI    A,1        ; NEW STATE
  1709.     STA    SR$STA        ; RECORD IT
  1710.     LDA    EA$FLG        ; A <-- END ACTION FLAGS
  1711.     ORI    SRDD        ; SYNC. RECEIVER DISCARDING DATA
  1712.     STA    EA$FLG        ; SAVE UPDATED FLAGS
  1713.     POP    H        ; RESTORE HL
  1714.     POP    PSW
  1715.     EI
  1716.     RET            ; RETURN FROM INTERRUPT
  1717.  
  1718. ;    Here if synchronous receiver state 1, discarding data
  1719. SR$S1    EQU    $
  1720.     IN    STAT73        ; READ STATUS
  1721.     ANI    RXIRA
  1722.     JNZ    SR$DR        ; IF (END-OF-FRAME) GOTO SR$DR
  1723. ;    Here if receiver has data to unload
  1724.     IN    RXDR73        ; READ CHARACTER
  1725.     POP    PSW
  1726.     EI
  1727.     RET            ; RETURN FROM INTERRUPT
  1728. ;    Here if discarding results
  1729. SR$DR    EQU    $
  1730.     IN    RXIR73        ; READ FRAME RESULTS
  1731.     PUSH    B        ; PRESERVE BC
  1732. SR$DRA    EQU    $
  1733.     IN    STAT73        ; READ STATUS
  1734.     MOV    B,A        ; COPY STATUS TO B
  1735.     ANI    RINTP
  1736.     JZ    SR$DRB        ; IF (RESULTS COMPLETE) GOTO SR$DRB
  1737.     MOV    A,B        ; RESTORE STATUS
  1738.     ANI    RXIRA
  1739.     JZ    SR$DRA        ; IF (NO RESULTS) GOTO SR$DRA
  1740. ;    Ready to read one byte of results code
  1741.     IN    RXIR73        ; READ RESULTS
  1742.     JMP    SR$DRA        ; WAIT FOR MORE, IF ANY
  1743. ;    Results are now complete
  1744. SR$DRB    EQU    $
  1745.     POP    B        ; RESTORE BC
  1746.     POP    PSW
  1747.     EI
  1748.     RET            ; RETURN FROM INTERRUPT
  1749. ;    PAGE
  1750.  
  1751. ;    Command and Immediate Results routines for 8273
  1752.  
  1753. SCMDOT    EQU    $
  1754.     MOV    B,M        ; B <-- PARAMETER COUNT
  1755.     INX    H        ; ADVANCE TO COMMAND BYTE
  1756. CMD1    EQU    $
  1757.     IN    STAT73        ; READ STATUS
  1758.     RLC            ; MOVE CBSY INTO CARRY
  1759.     JC    CMD1        ; IF (CBSY <> 0) GOTO CMD1
  1760.     MOV    A,M        ; A <-- COMMAND BYTE
  1761.     OUT    CMND73        ; WRITE COMMAND
  1762. CMD2    EQU    $
  1763.     MOV    A,B        ; A <-- PARAMETER COUNT
  1764.     ANA    A
  1765.     RZ            ; IF (COUNT = 0) RETURN
  1766.     INX    H        ; ADVANCE POINTER
  1767.     DCR    B        ; DECREMENT PARAMETER COUNT
  1768. CMD3    EQU    $
  1769.     IN    STAT73        ; READ STATUS
  1770.     ANI    CPBF        ; MASK COMMAND PARAMETER BUFFER FULL
  1771.     JNZ    CMD3        ; IF (CPBF <> 0) GOTO CMD3
  1772.     MOV    A,M        ; A <-- PARAMETER
  1773.     OUT    PARM73        ; WRITE PARAMETER
  1774.     JMP    CMD2        ; CHECK FOR MORE PARAMETERS
  1775.  
  1776.  
  1777.  
  1778. SRSLIN    EQU    $
  1779.     IN    STAT73        ; READ STATUS
  1780.     ANI    CRBF        ; MASK COMMAND RESULTS BUFFER FULL
  1781.     JZ    SRSLIN        ; IF (CRBF = 0) GOTO SRSLIN
  1782.     IN    RESL73        ; READ RESULTS
  1783.     RET
  1784. ;    PAGE
  1785.  
  1786. ;    Messages
  1787.  
  1788. ;
  1789. ;    TNC's SIGNATURE
  1790. TNCID    EQU    $
  1791.     DB    'VADCG/ASHBY-2716 Terminal Node Controller'
  1792.     DB    CR,LF
  1793.     DB    'KISS Protocol Firmware Version 1.03   08 FEB 87'
  1794.     DB    CR,LF,LF
  1795.  
  1796. ;
  1797. ;    COMMAND SEQUENCES FOR 8273 CONTROLLER
  1798. DTRANS    DB    1,97H,1
  1799. OPMODE    DB    1,91H,03H
  1800. SERIO    DB    1,0A0H,1
  1801. SSDTR    DB    1,0A3H,4
  1802. STRTS    DB    1,0A3H,1
  1803. DARTS    DB    1,63H,0FEH
  1804. SRDIS    DB    0,0C5H
  1805. RPA    DB    0,22H
  1806.     END
  1807.